﻿// FormsAuthenticationHelper.cs
//

using System;
using System.ComponentModel;
using System.Linq;
using System.Security.Principal;
using System.ServiceModel.DomainServices.Server.ApplicationServices;
using System.Web;
using System.Web.Security;

[assembly: PreApplicationStartMethod(typeof(FormsAuthenticationHelper), "Initialize")]

namespace System.ServiceModel.DomainServices.Server.ApplicationServices {

    /// <internalonly />
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static class FormsAuthenticationHelper {

        private static Type _authenticationServiceType;

        internal static void Enable(Type authenticationServiceType) {
            _authenticationServiceType = authenticationServiceType;
        }

        /// <internalonly />
        public static void Initialize() {
            WebContext.Initialized += OnApplicationInitialized;
        }

        private static void OnApplicationInitialized(object sender, EventArgs e) {
            HttpApplication application = (HttpApplication)sender;
            application.PostAuthenticateRequest += OnApplicationPostAuthenticateRequest;
        }

        private static void OnApplicationPostAuthenticateRequest(object sender, EventArgs e) {
            if (_authenticationServiceType == null) {
                return;
            }

            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;
            FormsIdentity userIdentity = context.User.Identity as FormsIdentity;

            if ((userIdentity != null) && userIdentity.IsAuthenticated) {
                DomainServiceContext serviceContext =
                    new DomainServiceContext(new AuthenticationServiceProvider(context),
                                             DomainOperationType.Query);
                UserBase user = Authentication.GetUser(_authenticationServiceType, serviceContext);
                if ((user != null) && (user.Roles != null)) {
                    context.User = new GenericPrincipal(userIdentity, user.Roles.ToArray());
                }
            }
        }


        private sealed class AuthenticationServiceProvider : IServiceProvider {

            private HttpContext _context;

            public AuthenticationServiceProvider(HttpContext httpContext) {
                _context = httpContext;
            }

            public object GetService(Type serviceType) {
                if (serviceType == typeof(IPrincipal)) {
                    return _context.User;
                }
                if (serviceType == typeof(HttpContext)) {
                    return _context;
                }
                if (serviceType == typeof(HttpContextBase)) {
                    return new HttpContextWrapper(_context);
                }
                return ((IServiceProvider)_context).GetService(serviceType);
            }
        }
    }
}
